DWORD dwFlags;
CHAR szDevice[CCHDEVICENAME];
} MONITORINFOEXA2;
-
+
MONITORINFOEXA2 monitor_info;
HDC hDC;
PFN_ProcessIdToSessionId processIdToSessionId;
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-
+
if (display_name_cache != NULL)
return display_name_cache;
gdk_win32_display_get_n_screens (GdkDisplay *display)
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
-
+
return 1;
}
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
- return FALSE;
+ return TRUE;
+}
+
+static HWND _hwnd_next_viewer = NULL;
+static int debug_indent = 0;
+
+/*
+ * maybe this should be integrated with the default message loop - or maybe not ;-)
+ */
+static LRESULT CALLBACK
+inner_clipboard_window_procedure (HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam)
+{
+ switch (message)
+ {
+ case WM_DESTROY: /* remove us from chain */
+ {
+ ChangeClipboardChain (hwnd, _hwnd_next_viewer);
+ PostQuitMessage (0);
+ return 0;
+ }
+ case WM_CHANGECBCHAIN:
+ {
+ HWND hwndRemove = (HWND) wparam; /* handle of window being removed */
+ HWND hwndNext = (HWND) lparam; /* handle of next window in chain */
+
+ if (hwndRemove == _hwnd_next_viewer)
+ _hwnd_next_viewer = hwndNext == hwnd ? NULL : hwndNext;
+ else if (_hwnd_next_viewer != NULL)
+ return SendMessage (_hwnd_next_viewer, message, wparam, lparam);
+
+ return 0;
+ }
+#ifdef WM_CLIPBOARDUPDATE
+ case WM_CLIPBOARDUPDATE:
+#endif
+ case WM_DRAWCLIPBOARD:
+ {
+ int success;
+ HWND hwndOwner;
+ UINT nFormat = 0;
+ GdkEvent *event;
+ GdkWindow *owner;
+
+ success = OpenClipboard (hwnd);
+ g_return_val_if_fail (success, 0);
+ hwndOwner = GetClipboardOwner ();
+ owner = gdk_win32_window_lookup_for_display (_gdk_display, hwndOwner);
+ if (owner == NULL)
+ owner = gdk_win32_window_foreign_new_for_display (_gdk_display, hwndOwner);
+
+ GDK_NOTE (DND, g_print (" drawclipboard owner: %p", hwndOwner));
+
+ if (_gdk_debug_flags & GDK_DEBUG_DND)
+ {
+ while ((nFormat = EnumClipboardFormats (nFormat)) != 0)
+ g_print ("%s ", _gdk_win32_cf_to_string (nFormat));
+ }
+
+ GDK_NOTE (DND, g_print (" \n"));
+
+ event = gdk_event_new (GDK_OWNER_CHANGE);
+ event->owner_change.window = _gdk_root;
+ event->owner_change.owner = owner;
+ event->owner_change.reason = GDK_OWNER_CHANGE_NEW_OWNER;
+ event->owner_change.selection = GDK_SELECTION_CLIPBOARD;
+ event->owner_change.time = _gdk_win32_get_next_tick (0);
+ event->owner_change.selection_time = GDK_CURRENT_TIME;
+ _gdk_win32_append_event (event);
+
+ CloseClipboard ();
+
+ if (_hwnd_next_viewer != NULL)
+ return SendMessage (_hwnd_next_viewer, message, wparam, lparam);
+
+ /* clear error to avoid confusing SetClipboardViewer() return */
+ SetLastError (0);
+ return 0;
+ }
+ default:
+ /* Otherwise call DefWindowProcW(). */
+ GDK_NOTE (EVENTS, g_print (" DefWindowProcW"));
+ return DefWindowProc (hwnd, message, wparam, lparam);
+ }
+}
+
+static LRESULT CALLBACK
+_clipboard_window_procedure (HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam)
+{
+ LRESULT retval;
+
+ GDK_NOTE (EVENTS, g_print ("%s%*s%s %p",
+ (debug_indent > 0 ? "\n" : ""),
+ debug_indent, "",
+ _gdk_win32_message_to_string (message), hwnd));
+ debug_indent += 2;
+ retval = inner_clipboard_window_procedure (hwnd, message, wparam, lparam);
+ debug_indent -= 2;
+
+ GDK_NOTE (EVENTS, g_print (" => %I64d%s", (gint64) retval, (debug_indent == 0 ? "\n" : "")));
+
+ return retval;
+}
+
+/*
+ * Creates a hidden window and adds it to the clipboard chain
+ */
+static HWND
+_gdk_win32_register_clipboard_notification (void)
+{
+ WNDCLASS wclass = { 0, };
+ HWND hwnd;
+ ATOM klass;
+
+ wclass.lpszClassName = "GdkClipboardNotification";
+ wclass.lpfnWndProc = _clipboard_window_procedure;
+ wclass.hInstance = _gdk_app_hmodule;
+
+ klass = RegisterClass (&wclass);
+ if (!klass)
+ return NULL;
+
+ hwnd = CreateWindow (MAKEINTRESOURCE (klass),
+ NULL, WS_POPUP,
+ 0, 0, 0, 0, NULL, NULL,
+ _gdk_app_hmodule, NULL);
+ if (!hwnd)
+ goto failed;
+
+ SetLastError (0);
+ _hwnd_next_viewer = SetClipboardViewer (hwnd);
+
+ if (_hwnd_next_viewer == NULL && GetLastError() != 0)
+ goto failed;
+
+ /* FIXME: http://msdn.microsoft.com/en-us/library/ms649033(v=VS.85).aspx */
+ /* This is only supported by Vista, and not yet by mingw64 */
+ /* if (AddClipboardFormatListener (hwnd) == FALSE) */
+ /* goto failed; */
+
+ return hwnd;
+
+failed:
+ g_critical ("Failed to install clipboard viewer");
+ UnregisterClass (MAKEINTRESOURCE (klass), _gdk_app_hmodule);
+ return NULL;
}
static gboolean
gdk_win32_display_request_selection_notification (GdkDisplay *display,
- GdkAtom selection)
+ GdkAtom selection)
{
- return FALSE;
+ static HWND hwndViewer = NULL;
+ gboolean ret = FALSE;
+
+ GDK_NOTE (DND,
+ g_print ("gdk_display_request_selection_notification (..., %s)",
+ gdk_atom_name (selection)));
+
+ if (selection == GDK_SELECTION_CLIPBOARD ||
+ selection == GDK_SELECTION_PRIMARY)
+ {
+ if (!hwndViewer)
+ {
+ hwndViewer = _gdk_win32_register_clipboard_notification ();
+ GDK_NOTE (DND, g_print (" registered"));
+ }
+ ret = (hwndViewer != NULL);
+ }
+ else
+ {
+ GDK_NOTE (DND, g_print (" unsupported"));
+ ret = FALSE;
+ }
+
+ GDK_NOTE (DND, g_print (" -> %s\n", ret ? "TRUE" : "FALSE"));
+ return ret;
}
static gboolean
GSourceFunc callback,
gpointer user_data);
-static void append_event (GdkEvent *event);
static gboolean is_modally_blocked (GdkWindow *window);
/* Private variable declarations
event->focus_change.in = in;
gdk_event_set_device (event, device);
- append_event (event);
+ _gdk_win32_append_event (event);
}
static void
event->grab_broken.grab_window = grab_window;
gdk_event_set_device (event, device);
- append_event (event);
+ _gdk_win32_append_event (event);
}
static LRESULT
event->any.send_event = InSendMessage ();
}
-static void
-append_event (GdkEvent *event)
+void
+_gdk_win32_append_event (GdkEvent *event)
{
GList *link;
event->crossing.state = 0; /* FIXME: Set correctly */
gdk_event_set_device (event, _gdk_display->core_pointer);
- append_event (event);
+ _gdk_win32_append_event (event);
if (type == GDK_ENTER_NOTIFY &&
window->extension_events != 0)
_gdk_device_wintab_update_window_coords (window);
}
-
+
/* The check_extended flag controls whether to check if the windows want
* events from extended input devices and if the message should be skipped
* because an extended input device is active
event->configure.x = point.x;
event->configure.y = point.y;
- append_event (event);
+ _gdk_win32_append_event (event);
}
}
event->button.button = button;
gdk_event_set_device (event, _gdk_display->core_pointer);
- append_event (event);
+ _gdk_win32_append_event (event);
}
static void
if (msg->wParam == VK_MENU)
event->key.state &= ~GDK_MOD1_MASK;
- append_event (event);
+ _gdk_win32_append_event (event);
return_val = TRUE;
break;
gdk_event_set_device (event, GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard);
build_wm_ime_composition_event (event, msg, wbuf[i], key_state);
- append_event (event);
+ _gdk_win32_append_event (event);
}
if (window->event_mask & GDK_KEY_RELEASE_MASK)
gdk_event_set_device (event, GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard);
build_wm_ime_composition_event (event, msg, wbuf[i], key_state);
- append_event (event);
+ _gdk_win32_append_event (event);
}
}
return_val = TRUE;
event->motion.is_hint = FALSE;
gdk_event_set_device (event, _gdk_display->core_pointer);
- append_event (event);
+ _gdk_win32_append_event (event);
return_val = TRUE;
break;
event->scroll.state = build_pointer_event_state (msg);
gdk_event_set_device (event, _gdk_display->core_pointer);
- append_event (event);
+ _gdk_win32_append_event (event);
return_val = TRUE;
break;
event = gdk_event_new (msg->wParam ? GDK_MAP : GDK_UNMAP);
event->any.window = window;
- append_event (event);
+ _gdk_win32_append_event (event);
if (event->any.type == GDK_UNMAP)
{
event = gdk_event_new (GDK_DELETE);
event->any.window = window;
- append_event (event);
+ _gdk_win32_append_event (event);
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
event = gdk_event_new (GDK_DESTROY);
event->any.window = window;
- append_event (event);
+ _gdk_win32_append_event (event);
return_val = TRUE;
break;
event->selection.window = window;
event->selection.selection = GDK_SELECTION_CLIPBOARD;
event->selection.time = _gdk_win32_get_next_tick (msg->time);
- append_event (event);
+ _gdk_win32_append_event (event);
}
else
{
}
/* We need to render to clipboard immediately, don't call
- * append_event()
+ * _gdk_win32_append_event()
*/
event = gdk_event_new (GDK_SELECTION_REQUEST);
event->selection.window = window;
g_object_ref (window);
if (_gdk_input_other_event (event, msg, window))
- append_event (event);
+ _gdk_win32_append_event (event);
else
gdk_event_free (event);